/*
 * yauosk - Yet Another Useless Operating System Kernel
 *
 * Copyright (c) 2009-2010 Matteo Cicuttin
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 * derived from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "asm.h"

    .globl  start
    .code16
       
start:      cli                 # No interrups
            cld                 # String operations dir
            xorw    %ax, %ax    # Init segment registers
            movw    %ax, %es
            movw    %ax, %ds
            movw    %ax, %ss
            
# Setup stack, we grow downward starting at 0x7c00
            movw    $start, %sp
            
# Enable A20 gate
            
a20_loop.1: inb     $0x64, %al
            testb   $0x2, %al
            jnz     a20_loop.1
            movb    $0xd1, %al
            outb    %al, $0x64
            
a20_loop.2: inb     $0x64, %al
            testb   $0x02, %al
            jnz     a20_loop.2
            movb    $0xdf, %al
            outb    %al, $0x60

# Switch to protected mode and enable address translation

            cli                         # Make sure interrupts are disabled
            
            movl    $0x80000, %eax      # Setup page directory
            movl    $0x81003, (%eax)
            movl    $0x82003, 0xC00(%eax)
            
            movl    $256, %ecx          # Identity paging for the first meg
            movl    $0x00000003, %edx
            movl    $0x81000, %eax
pt0.loop:   movl    %edx, (%eax)
            addl    $0x4, %eax
            addl    $0x1000, %edx
            dec     %ecx
            jnz     pt0.loop

            movl    $1024, %ecx          # Map 4megs to 0x100000
            movl    $0x00100003, %edx
            movl    $0x82000, %eax          
pt1.loop:   movl    %edx, (%eax)
            addl    $0x4, %eax
            addl    $0x1000, %edx
            dec     %ecx
            jnz     pt1.loop            
            
            movl    $0x80000, %eax
            movl    %eax, %cr3
            lgdt    gdt_desc
            movl    %cr0, %eax
            orl     $0x80000001, %eax
            #orl		$0x1, %eax
			movl	%eax, %cr0
			ljmp    $0x08,$pm_start  # 0x08: code segment descriptor in GDT
	   
	.code32
pm_start:	movw    $0x10,%ax        # 0x10: data segment descriptor in GDT
            movw    %ax,%ds
            movw    %ax,%es
			movw    %ax,%fs
			movw    %ax,%gs
            movw    %ax,%ss
            
            movl    $0xc004ffff, %esp
			call	loader

spin:		jmp spin


	
	.p2align 2
gdt:            
    .word 0x0,0x0,0x0,0x0           # Null entry
    SEGDESC(0x0, 0xffffffff, SEG_X | SEG_R | SEG_RING_0 | SEG_P, 0x0c)
    SEGDESC(0x0, 0xffffffff, SEG_W | SEG_RING_0 | SEG_P, 0x0c)
	SEGDESC(0x0, 0xffffffff, SEG_X | SEG_R | SEG_RING_3 | SEG_P, 0x0c)
	SEGDESC(0x0, 0xffffffff, SEG_W | SEG_RING_3 | SEG_P, 0x0c)
	
gdt_end:

gdt_desc:       .word   gdt_end - gdt - 1
                .long   gdt
                
